
let activeEffect
/**
 * 关于依赖
 * 从数据的角度,依赖是指依赖该属性的[副作用函数]
 */
function cleanup(effectFn) {
    for (let i = 0; i < effectFn.deps.length; i++) {
        effectFn.deps[i].delete(effectFn)
    }
    effectFn.deps.length = 0
}
function effect(fn) {
    const effectFn = () => {
        console.log('effectFn executed')
        cleanup(effectFn)
        activeEffect = effectFn
        fn()
    }
    effectFn.deps = []
    effectFn()
}

/**
 * 副作用函数中被读取的数据必须被代理
 */
function proxyData(data) {
    let bucket = new WeakMap()
    function track(target, key) {
        if (!activeEffect) return target[key]
        let depsMap = bucket.get(target)
        if (!depsMap) {
            bucket.set(target, depsMap = new Map())
        }
        let deps = depsMap.get(key)
        if (!deps) {
            depsMap.set(key, deps = new Set())
        }
        deps.add(activeEffect)
        activeEffect.deps.push(deps)
    }

    function trigger(target, key) {
        let depsMap = bucket.get(target)
        if (!depsMap) {
            return
        }
        const deps = depsMap.get(key)
        let effectsToRun = new Set(deps)
        effectsToRun && effectsToRun.forEach(fn => fn())
    }
    return new Proxy(data, {
        get(target, key) {
            track(target, key)
            return target[key]
        },
        set(target, key, newVal) {
            target[key] = newVal
            trigger(target, key)
        }
    })
}


//test code
// let obj = { text: "hello" }
let obj = { ok: true, text: "hello" }
obj = proxyData(obj)

// 副作用函数
function readObj() {
    console.log(obj.ok ? obj.text : 'not')
}
// 执行副作用函数，触发读取
effect(readObj)
// 1 秒后修改响应式数据
setTimeout(() => {
    obj.ok = false
}, 1000)
setTimeout(() => {
    obj.text = "test"
}, 1000)





